# 提醒服务
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime, timedelta
import logging
import ctypes
import threading

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class ReminderService:
    """提醒服务类 - 使用APScheduler实现定时提醒"""
    
    def __init__(self, app=None):
        self.scheduler = BackgroundScheduler()
        self.app = app
        self.reminded_items = {}  # 已提醒的项目记录（格式：{key: timestamp}）
        
        if app is not None:
            self.init_app(app)
    
    def init_app(self, app):
        """初始化应用"""
        self.app = app
        
        # 添加定时任务
        # 每分钟检查待办事项的截止日期
        self.scheduler.add_job(
            func=self.check_todo_deadlines,
            trigger='interval',
            minutes=1,
            id='check_todo_deadlines',
            name='检查待办截止日期',
            replace_existing=True
        )
        
        # 每天检查目标进度
        self.scheduler.add_job(
            func=self.check_goal_progress,
            trigger='cron',
            hour=9,
            minute=0,
            id='check_goal_progress',
            name='检查目标进度',
            replace_existing=True
        )
        
        # 每1分钟检查日程提醒（实时准确）
        self.scheduler.add_job(
            func=self.check_event_reminders,
            trigger='interval',
            minutes=1,
            id='check_event_reminders',
            name='检查日程提醒',
            replace_existing=True
        )
        
        # 每天凌晨3点清理已提醒记录（防止内存无限增长）
        self.scheduler.add_job(
            func=self.clear_reminder_cache,
            trigger='cron',
            hour=3,
            minute=0,
            id='clear_reminder_cache',
            name='清理提醒缓存',
            replace_existing=True
        )
        
        # 启动调度器
        if not self.scheduler.running:
            self.scheduler.start()
            logger.info('提醒服务已启动')
    
    def check_todo_deadlines(self):
        """检查待办事项的截止日期（提前1分钟提醒）"""
        # 先清理过期记录
        self.clear_expired_reminders()
        
        with self.app.app_context():
            from models.todo import Todo
            from datetime import datetime, timedelta
            
            now = datetime.utcnow()  # 修复：使用UTC时间与数据库时间一致
            one_minute_later = now + timedelta(minutes=1)
            two_minutes_later = now + timedelta(minutes=2)
            
            # 查找1分钟后将到期的任务（提前1分钟提醒）
            # 查找范围：now+1分钟 到 now+2分钟之间，避免重复提醒
            upcoming_todos = Todo.query.filter(
                Todo.completed == False,
                Todo.deadline >= one_minute_later,
                Todo.deadline < two_minutes_later
            ).all()
            
            if upcoming_todos:
                logger.info(f'发现 {len(upcoming_todos)} 个即将到期的待办事项')
                for todo in upcoming_todos:
                    # 生成唯一标识（待办ID + 截止日期的小时和分钟）
                    reminder_key = f"todo_{todo.id}_{todo.deadline.strftime('%Y%m%d%H%M')}"
                    
                    # 检查是否已提醒过
                    if reminder_key not in self.reminded_items:
                        self.reminded_items[reminder_key] = now.timestamp()
                        deadline_str = todo.deadline.strftime("%H:%M")
                        self.send_notification(
                            title='⏰ 待办到期提醒',
                            message=f'任务 "{todo.title}" 将在 {deadline_str} 到期，请注意！'
                        )
                        logger.info(f'已提醒待办: {todo.title} (key: {reminder_key})')
                    else:
                        logger.debug(f'跳过重复提醒: {todo.title} (key: {reminder_key})')
    
    def check_goal_progress(self):
        """检查目标进度"""
        with self.app.app_context():
            from models.goal import Goal
            
            # 查找进行中但进度低于预期的目标
            goals = Goal.query.filter_by(status='进行中').all()
            
            for goal in goals:
                if goal.target_date and goal.target_date < datetime.utcnow():  # 修复：使用UTC时间
                    logger.info(f'目标 "{goal.title}" 已超过目标日期')
                    self.send_notification(
                        title='目标提醒',
                        message=f'目标 "{goal.title}" 已超过目标完成日期，当前进度 {goal.progress}%'
                    )
    
    def check_event_reminders(self):
        """检查日程提醒"""
        # 先清理过期记录
        self.clear_expired_reminders()
        
        with self.app.app_context():
            from models.schedule import Event
            from datetime import datetime, timedelta
            
            now = datetime.utcnow()  # 修复：使用UTC时间与数据库一致
            
            # 查找即将开始的事件（1小时内）
            upcoming_events = Event.query.filter(
                Event.start_time > now,
                Event.start_time <= now + timedelta(hours=1)
            ).all()
            
            for event in upcoming_events:
                # 计算提醒时间（提前N分钟）
                reminder_time = event.start_time - timedelta(minutes=event.reminder_minutes)
                
                # 在提醒时间前后1分钟的窗口内提醒，避免错过
                one_minute_before = reminder_time - timedelta(minutes=1)
                one_minute_after = reminder_time + timedelta(minutes=1)
                
                if one_minute_before <= now <= one_minute_after and now < event.start_time:
                    # 生成唯一标识（事件ID + 开始时间 + 提醒分钟数）
                    reminder_key = f"event_{event.id}_{event.start_time.strftime('%Y%m%d%H%M')}_{event.reminder_minutes}"
                    
                    # 检查是否已提醒过
                    if reminder_key not in self.reminded_items:
                        self.reminded_items[reminder_key] = now.timestamp()
                        logger.info(f'发送事件提醒: {event.title}（提前{event.reminder_minutes}分钟）')
                        self.send_notification(
                            title='📅 日程提醒',
                            message=f'事件 "{event.title}" 将在 {event.start_time.strftime("%H:%M")} 开始'
                        )
                    else:
                        logger.debug(f'跳过重复提醒: {event.title} (key: {reminder_key})')
    
    def clear_expired_reminders(self):
        """清理过期的提醒记录（超过24小时的记录）"""
        now = datetime.utcnow().timestamp()  # 修复：使用UTC时间
        expired_keys = [
            key for key, timestamp in self.reminded_items.items()
            if now - timestamp > 86400  # 86400秒 = 24小时
        ]
        
        for key in expired_keys:
            del self.reminded_items[key]
        
        if expired_keys:
            logger.info(f'已清理 {len(expired_keys)} 条过期提醒记录（24小时前）')
    
    def clear_reminder_cache(self):
        """清理所有提醒记录缓存（每天凌晨执行，兜底清理）"""
        cache_size = len(self.reminded_items)
        self.reminded_items.clear()
        logger.info(f'已清理 {cache_size} 条提醒记录缓存')
    
    def send_notification(self, title, message):
        """发送Windows系统弹框通知（需手动点击确认）
        
        Args:
            title: 通知标题
            message: 通知内容
        """
        # 记录日志
        logger.info(f'[通知] {title}: {message}')
        
        # 在新线程中显示Windows系统弹框（避免阻塞定时任务）
        def show_messagebox():
            try:
                # Windows MessageBox 样式常量
                MB_OK = 0x0  # 确定按钮
                MB_ICONINFORMATION = 0x40  # 信息图标
                MB_SYSTEMMODAL = 0x1000  # 系统级模态对话框（始终置顶）
                
                # 调用Windows API显示系统弹框（阻塞式，需点击确认，始终置顶）
                ctypes.windll.user32.MessageBoxW(
                    0,  # 父窗口句柄（0表示无父窗口）
                    message,  # 消息内容
                    title,  # 标题
                    MB_OK | MB_ICONINFORMATION | MB_SYSTEMMODAL  # 样式：确定按钮 + 信息图标 + 系统模态（置顶）
                )
                logger.info(f'用户已确认通知: {title}')
            except Exception as e:
                logger.error(f'显示Windows弹框失败: {e}')
        
        # 启动新线程显示弹框（不阻塞主线程）
        notification_thread = threading.Thread(target=show_messagebox, daemon=True)
        notification_thread.start()
    
    def shutdown(self):
        """关闭调度器"""
        if self.scheduler.running:
            self.scheduler.shutdown()
            logger.info('提醒服务已停止')

# 全局实例
reminder_service = ReminderService()

